package com.micro;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;


public class PermutationTester {
    
    public static class Permutation<T> {
        private int less;
        private int max[];
        private int index[];
        private T data;
        private PermutationIteratorHandler<T> handler;
        
        public Permutation(int n, int m, T data) {
            this.index = new int[n];
            this.data = data;
            this.max = new int[n];
            for (int i = m - n + 1, j = 0; i <= m; ++i, ++j) {
                this.max[j] = i;
            }
            this.less = n - 1;
        }
        
        public PermutationIteratorHandler<T> getHandler() {
            return handler;
        }
        public void setHandler(PermutationIteratorHandler<T> handler) {
            this.handler = handler;
        }
        public int getLess() {
            return less;
        }
        public int[] getMax() {
            return max;
        }
        public void setMax(int[] max) {
            this.max = max;
        }
        
        public T getData() {
            return data;
        }
        public void setData(T data) {
            this.data = data;
        }
        
        private void iterate(int i, int idx) {
            if (idx == this.less) {
                int []index = this.index;
                int size = this.max[idx];
                for (int j = i + 1; j < size; ++j) {
                    index[idx] = j;
                    this.handler.handle(index, this.data);
                }
            } else if (idx < this.less) {
                int size = this.max[idx];
                int nextIdx = idx + 1;
                for (int j = i + 1; j < size; ++j) {
                    this.index[idx] = j;
                    iterate(j, nextIdx);
                }
            }
        }
        
        public void iterate() {
            iterate(-1, 0);
            this.handler.end(this.data);
        }
    }
    
    public static interface PermutationIteratorHandler<T> {
//        boolean before(T data);
        void handle(int []index, T data);
        void end(T data);
    }
    public static class DefaultPermutationHandler implements PermutationIteratorHandler<Map<String, Integer>> {
        @Override
        public void handle(int[] index, Map<String, Integer> data) {
            Integer count = data.get("count");
            ++count;
            data.put("count", count);
        }
        @Override
        public void end(Map<String, Integer> data) {
            System.err.println("数量：" + data.get("count"));
        }
        
    }
    
    public static class AlphaPermutationHandler implements PermutationIteratorHandler<String> {
        StringBuilder sb = new StringBuilder();
        @Override
        public void handle(int[] index, String data) {
            sb.setLength(0);
            for (int i = 0; i < index.length; ++i) {
                sb.append(data.charAt(index[i]));
            }
            System.err.println(sb);
        }
        @Override
        public void end(String data) { }
        
    }
    
    public static void main(String[] args) throws Exception {
//        Map<String, Integer> map = new HashMap<>(1);
//        map.put("count", 0);
//        Permutation<Map<String, Integer>> p = new Permutation<>(6, 33, map);
//        p.setHandler(new DefaultPermutationHandler());
        
        String str1 = "ABCD";
        Permutation<String> p = new Permutation<>(3, str1.length(), str1);
        p.setHandler(new AlphaPermutationHandler());
        long curr1 = System.currentTimeMillis();
        p.iterate();
        System.err.println("结束：" + ((System.currentTimeMillis() - curr1) / 1000.0));
    }
	
}
